package jmine.tec.rpc.common.serialization.json;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;

import jmine.tec.json.JSON;
import jmine.tec.json.JSONObject;
import jmine.tec.json.JSONString;
import jmine.tec.proxy.builder.ProxyBuilder;
import jmine.tec.proxy.chain.ChainElement;
import jmine.tec.rpc.common.entity.EntityRepresentation;
import jmine.tec.rpc.common.entity.EntityRest;
import jmine.tec.rpc.common.lazy.LazyRepresentation;
import jmine.tec.rpc.common.lazy.LazyRepresentationInitializer;
import jmine.tec.rpc.common.lazy.LazyRepresenterChain;
import jmine.tec.rpc.common.provider.RestServiceProvider;

/**
 * Conversos de representações lazy de objetos JSON.
 * 
 * @author lundberg
 */
public class JSONLazyRepresentationConverter extends AbstractJSONObjectConverter implements RestServiceProviderAware {

    private static final String CLASS = "&class";

    private static final String ID = "&id";

    private RestServiceProvider provider;

    /**
     * {@inheritDoc}
     */
    public boolean matchesJava(Object object) {
        return object instanceof LazyRepresentation;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected Object instantiate(JSONConversionContext context, JSON json) {
        @SuppressWarnings("unchecked")
        Class<? extends EntityRepresentation> representationClass =
                (Class<? extends EntityRepresentation>) context.toJava(json.getProperty(CLASS));
        Serializable representationId = (Serializable) context.toJava(json.getProperty(ID));
        EntityRest<?> service = this.provider.provideByRepresentation(representationClass);
        LazyRepresentationInitializer initializer = new LazyRepresentationInitializer(service, representationId);
        ChainElement chain = new LazyRepresenterChain(initializer);
        ProxyBuilder builder = new ProxyBuilder();
        builder.setType(representationClass);
        builder.setChainElements(Collections.singletonList(chain));
        builder.setInterfaces(Arrays.asList(new Class<?>[]{ LazyRepresentation.class }));
        return builder.build();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void fillObject(JSONConversionContext context, JSON json, Object object) {
        // OK
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void fillJSON(JSONConversionContext context, Object object, JSONObject json) {
        LazyRepresentation lazy = (LazyRepresentation) object;
        json.setProperty(CLASS, context.toJSON(lazy.getLazyRepresentationInitializer().getRepresentationClass()));
        json.setProperty(ID, context.toJSON(lazy.getLazyRepresentationInitializer().getRepresentationId()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected JSON objectType() {
        return new JSONString("proxy");
    }

    /**
     * {@inheritDoc}
     */
    public void setProvider(RestServiceProvider provider) {
        this.provider = provider;
    }

}
